package service

import (
	"beesoft.ink/application/garage/app/g"
	"beesoft.ink/application/garage/app/model"
	"errors"
	"fmt"
	"github.com/golang-jwt/jwt"
	"github.com/labstack/echo/v4"
	"github.com/spf13/viper"
	"strconv"
	"time"
)

var Auth = auth{}

type auth struct{}

func (r auth) SendVerificationCode(ctx echo.Context, req *model.AuthSendVerificationCodeReq) (*model.AuthSendVerificationCodeRes, error) {
	res := new(model.AuthSendVerificationCodeRes)

	var user *model.User
	if err := g.DB().Where("phone", req.Phone).First(&user).Error; err != nil {
		return nil, err
	}
	if user == nil {
		return res, errors.New("phone not exist")
	}
	// todo 校验 发送频率

	verificationCode := "1234"
	// verificationCode := helper.RandomDigits(4)

	user.VerificationCode = verificationCode
	user.VerificationCodeExpiredAt = time.Now().Add(60 * time.Second)
	g.DB().Save(&user)

	//send, err := tencent.New().
	//	NewSms("login").
	//	Send(&tencent.SmsSendReq{
	//		PhoneNumber: req.Phone,
	//		TemplateId:  "111",
	//		TemplateParameters: []*string{
	//			helper.Ptr(verificationCode),
	//			// helper.Ptr("60"), // 60s
	//		},
	//	})
	//if err != nil {
	//	fmt.Printf("Auth SendVerificationCode error: %+v\n", err)
	//
	//	return res, err
	//}
	//fmt.Printf("Auth SendVerificationCode result: %+v\n", send)

	res.State = 1
	res.LeftSeconds = 60

	return res, nil
}
func (r auth) Login(ctx echo.Context, req *model.AuthLoginReq) (*model.AuthLoginRes, error) {
	res := new(model.AuthLoginRes)

	var (
		user *model.User
		err  error
	)

	switch req.Type {
	case model.LoginTypeUsernamePassword:
		user, err = r.LoginByUsernamePassword(req)
	case model.LoginTypeEmailVerificationCode:
		user, err = r.LoginByEmailVerificationCode(req)
	case model.LoginTypePhoneVerificationCode:
		user, err = r.LoginByPhoneVerificationCode(req)
	}

	if user != nil {
		token := jwt.New(jwt.SigningMethodHS256)

		claims := token.Claims.(jwt.MapClaims)
		claims["id"] = user.Id
		claims["name"] = user.Username
		claims["exp"] = time.Now().Add(time.Hour * 72).Unix() // 3days

		res.Token, err = token.SignedString([]byte(viper.GetString("server.key")))
		res.State = 1

		return res, err
	}

	return res, echo.ErrUnauthorized
}

func (r auth) Logout(ctx echo.Context) error {
	return nil
}
func (r auth) Profile(ctx echo.Context) (*model.User, error) {
	user := ctx.Get("token").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)

	id := claims["id"].(string)
	name := claims["name"].(string)
	fmt.Printf("id: %s, name: %s", id, name)

	var item *model.User
	if err := g.DB().First(&item, id).Error; err != nil {
		return nil, err
	}

	return item, nil
}

func (r auth) ParseAuth(ctx echo.Context) (*model.AuthUser, error) { // 解析认证用户
	user := new(model.AuthUser)

	token := ctx.Get("token").(*jwt.Token)
	claims := token.Claims.(jwt.MapClaims)
	userId := claims["id"].(string)
	user.Name = claims["name"].(string)

	id64, err := strconv.ParseUint(userId, 10, 32)
	if err != nil {
		return user, err
	}
	if id64 == 0 {
		return user, errors.New("no user id found")
	}
	user.Id = uint(id64)

	return user, nil
}
